home *** CD-ROM | disk | FTP | other *** search
/ Language/OS - Multiplatform Resource Library / LANGUAGE OS.iso / oper_sys / kerberos / pc / krb_libd.lha / Lib / Des / PCBC_ENC.C < prev    next >
Encoding:
C/C++ Source or Header  |  1991-07-23  |  6.8 KB  |  249 lines

  1. /*
  2.  * $Source: /afs/athena.mit.edu/astaff/project/kerberos/src/lib/des/RCS/pcbc_encrypt.c,v $
  3.  * $Author: jtkohl $
  4.  *
  5.  * Copyright 1985, 1986, 1987, 1988 by the Massachusetts Institute
  6.  * of Technology.
  7.  *
  8.  * For copying and distribution information, please see the file
  9.  * <mit-copyright.h>.
  10.  *
  11.  * These routines perform encryption and decryption using the DES
  12.  * private key algorithm, or else a subset of it-- fewer inner loops.
  13.  * ( AUTH_DES_ITER defaults to 16, may be less)
  14.  *
  15.  * Under U.S. law, this software may not be exported outside the US
  16.  * without license from the U.S. Commerce department.
  17.  *
  18.  * The key schedule is passed as an arg, as well as the cleartext or
  19.  * ciphertext.     The cleartext and ciphertext should be in host order.
  20.  *
  21.  * These routines form the library interface to the des facilities.
  22.  *
  23.  * spm 8/85    MIT project athena
  24.  */
  25.  
  26. #include <mit_copy.h>
  27. #include <stdio.h>
  28. #include <des.h>
  29. #include "des_intn.h"
  30.  
  31. extern int des_debug;
  32. extern int des_debug_print();
  33.  
  34. /*
  35.  * pcbc_encrypt is an "error propagation chaining" encrypt operation
  36.  * for DES, similar to CBC, but that, on encryption, "xor"s the
  37.  * plaintext of block N with the ciphertext resulting from block N,
  38.  * then "xor"s that result with the plaintext of block N+1 prior to
  39.  * encrypting block N+1. (decryption the appropriate inverse.  This
  40.  * "pcbc" mode propagates a single bit error anywhere in either the
  41.  * cleartext or ciphertext chain all the way through to the end. In
  42.  * contrast, CBC mode limits a single bit error in the ciphertext to
  43.  * affect only the current (8byte) block and the subsequent block.
  44.  *
  45.  * performs pcbc error-propagation chaining operation by xor-ing block
  46.  * N+1 with both the plaintext (block N) and the ciphertext from block
  47.  * N.  Either encrypts from cleartext to ciphertext, if encrypt != 0
  48.  * or decrypts from ciphertext to cleartext, if encrypt == 0
  49.  *
  50.  * NOTE-- the output is ALWAYS an multiple of 8 bytes long.  If not
  51.  * enough space was provided, your program will get trashed.
  52.  *
  53.  * For encryption, the cleartext string is null padded, at the end, to
  54.  * an integral multiple of eight bytes.
  55.  *
  56.  * For decryption, the ciphertext will be used in integral multiples
  57.  * of 8 bytes, but only the first "length" bytes returned into the
  58.  * cleartext.
  59.  *
  60.  * This is NOT a standard mode of operation.
  61.  *
  62.  */
  63.  
  64. int
  65. des_pcbc_encrypt(in,out,length,key,iv,encrypt)
  66.     des_cblock *in;        /* >= length bytes of inputtext */
  67.     des_cblock *out;        /* >= length bytes of outputtext */
  68.     register long length;    /* in bytes */
  69.     int encrypt;        /* 0 ==> decrypt, else encrypt */
  70.     des_key_schedule key;        /* precomputed key schedule */
  71.     des_cblock *iv;        /* 8 bytes of ivec */
  72. {
  73.     register unsigned long *input = (unsigned long *) in;
  74.     register unsigned long *output = (unsigned long *) out;
  75.     register unsigned long *ivec = (unsigned long *) iv;
  76.  
  77.     unsigned long i,j;
  78.     static unsigned long t_input[2];
  79.     static unsigned long t_output[2];
  80.     static unsigned char *t_in_p;
  81.     static unsigned long xor_0, xor_1;
  82.  
  83.     t_in_p = (unsigned char *) t_input;
  84.     if (encrypt) {
  85. #ifdef MUSTALIGN
  86.     if ((long) ivec & 3) {
  87.         bcopy((char *)ivec++,(char *)&xor_0,sizeof(xor_0));
  88.         bcopy((char *)ivec,(char *)&xor_1,sizeof(xor_1));
  89.     }
  90.     else
  91. #endif
  92.     {
  93.         xor_0 = *ivec++;
  94.         xor_1 = *ivec;
  95.     }
  96.  
  97.     for (i = 0; length > 0; i++, length -= 8) {
  98.         /* get input */
  99. #ifdef MUSTALIGN
  100.         if ((long) input & 3) {
  101.         bcopy((char *)input,(char *)&t_input[0],sizeof(t_input[0]));
  102.         bcopy((char *)(input+1),(char *)&t_input[1],sizeof(t_input[1]));
  103.         }
  104.         else
  105. #endif
  106.         {
  107.         t_input[0] = *input;
  108.         t_input[1] = *(input+1);
  109.         }
  110.  
  111.         /* zero pad */
  112.         if (length < 8) {
  113.         for (j = length; j <= 7; j++)
  114.             *(t_in_p+j)= 0;
  115.         }
  116.  
  117. #ifdef DEBUG
  118.         if (des_debug)
  119.         des_debug_print("clear",length,t_input[0],t_input[1]);
  120. #endif
  121.         /* do the xor for cbc into the temp */
  122.         t_input[0] ^= xor_0 ;
  123.         t_input[1] ^= xor_1 ;
  124.         /* encrypt */
  125.         (void) des_ecb_encrypt(t_input,t_output,key,encrypt);
  126.  
  127.         /*
  128.          * We want to XOR with both the plaintext and ciphertext
  129.          * of the previous block, before we write the output, in
  130.          * case both input and output are the same space.
  131.          */
  132. #ifdef MUSTALIGN
  133.         if ((long) input & 3) {
  134.         bcopy((char *)input++,(char *)&xor_0,sizeof(xor_0));
  135.         xor_0 ^= t_output[0];
  136.         bcopy((char *)input++,(char *)&xor_1,sizeof(xor_1));
  137.         xor_1 ^= t_output[1];
  138.         }
  139.         else
  140. #endif
  141.         {
  142.         xor_0 = *input++ ^ t_output[0];
  143.         xor_1 = *input++ ^ t_output[1];
  144.         }
  145.  
  146.  
  147.         /* copy temp output and save it for cbc */
  148. #ifdef MUSTALIGN
  149.         if ((long) output & 3) {
  150.         bcopy((char *)&t_output[0],(char *)output++,
  151.               sizeof(t_output[0]));
  152.         bcopy((char *)&t_output[1],(char *)output++,
  153.               sizeof(t_output[1]));
  154.         }
  155.         else
  156. #endif
  157.         {
  158.         *output++ = t_output[0];
  159.         *output++ = t_output[1];
  160.         }
  161.  
  162. #ifdef DEBUG
  163.         if (des_debug) {
  164.         des_debug_print("xor'ed",i,t_input[0],t_input[1]);
  165.         des_debug_print("cipher",i,t_output[0],t_output[1]);
  166.         }
  167. #endif
  168.     }
  169.     t_output[0] = 0;
  170.     t_output[1] = 0;
  171.     xor_0 = 0;
  172.     xor_1 = 0;
  173.     return 0;
  174.     }
  175.  
  176.     else {
  177.     /* decrypt */
  178. #ifdef MUSTALIGN
  179.     if ((long) ivec & 3) {
  180.         bcopy((char *)ivec++,(char *)&xor_0,sizeof(xor_0));
  181.         bcopy((char *)ivec,(char *)&xor_1,sizeof(xor_1));
  182.     }
  183.     else
  184. #endif
  185.     {
  186.         xor_0 = *ivec++;
  187.         xor_1 = *ivec;
  188.     }
  189.  
  190.     for (i = 0; length > 0; i++, length -= 8) {
  191.         /* get input */
  192. #ifdef MUSTALIGN
  193.         if ((long) input & 3) {
  194.         bcopy((char *)input++,(char *)&t_input[0],sizeof(t_input[0]));
  195.         bcopy((char *)input++,(char *)&t_input[1],sizeof(t_input[1]));
  196.         }
  197.         else
  198. #endif
  199.         {
  200.         t_input[0] = *input++;
  201.         t_input[1] = *input++;
  202.         }
  203.  
  204.         /* no padding for decrypt */
  205. #ifdef DEBUG
  206.         if (des_debug)
  207.         des_debug_print("cipher",i,t_input[0],t_input[1]);
  208. #else
  209. #ifdef lint
  210.         i = i;
  211. #endif
  212. #endif
  213.         /* encrypt */
  214.         (void) des_ecb_encrypt(t_input,t_output,key,encrypt);
  215. #ifdef DEBUG
  216.         if (des_debug)
  217.         des_debug_print("out pre xor",i,t_output[0],t_output[1]);
  218. #endif
  219.         /* do the xor for cbc into the output */
  220.         t_output[0] ^= xor_0 ;
  221.         t_output[1] ^= xor_1 ;
  222.         /* copy temp output */
  223. #ifdef MUSTALIGN
  224.         if ((long) output & 3) {
  225.         bcopy((char *)&t_output[0],(char *)output++,
  226.               sizeof(t_output[0]));
  227.         bcopy((char *)&t_output[1],(char *)output++,
  228.               sizeof(t_output[1]));
  229.         }
  230.         else
  231. #endif
  232.         {
  233.         *output++ = t_output[0];
  234.         *output++ = t_output[1];
  235.         }
  236.  
  237.         /* save xor value for next round */
  238.         xor_0 = t_output[0] ^ t_input[0];
  239.         xor_1 = t_output[1] ^ t_input[1];
  240.  
  241. #ifdef DEBUG
  242.         if (des_debug)
  243.         des_debug_print("clear",i,t_output[0],t_output[1]);
  244. #endif
  245.     }
  246.     return 0;
  247.     }
  248. }
  249.